/*
 * commandLine.c
 *
 *  Created on: Dec 25, 2009
 *      Author: jkeller
 */
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <argtable2.h>
#include "main.h"

#define VERBOSE_VAL       1
#define VERSION_VAL       2
#define QUERY_VAL         3
#define QUERY_INFO_VAL    4
#define QUERY_LIST_VAL    5
#define QUERY_SCRIPTS_VAL 6

#define SPACE_27          "                           "
int
parseCommandLine( int             argc,
                  char **         argv,
                  command *       todo,
                  int *           be_verbose,
                  const char * ** fileNames,
                  int *           numfilenames,
                  char **         queryFormat,
                  char **         root,
                  FILE *          outDest,
                  FILE*           errorDest )
{

    assert( todo != NULL );
    assert( fileNames != NULL );
    assert( numfilenames != NULL );
    assert( be_verbose != NULL );

    *todo = cmd_nothing;

    int retval = 0;

    const char default_query_scripts_arg[] = "all";

    struct arg_lit *help = arg_lit0( "h?", "help", "Display's help (this message)." );
    struct arg_lit *verbose = arg_lit0( NULL, "verbose", "Enables debugging information." );
    struct arg_lit *version = arg_lit0( NULL, "version", "Displays the version information." );

    struct arg_str *root_opt= arg_str0( "r", "root", "<str>", "Points to the install root." );

    struct arg_lit *query_tags= arg_lit0( NULL, "querytags", "Queries known tags." );
    struct arg_lit *query= arg_lit0( "q", "query", "Queries installed or uninstalled packages." );
    struct arg_rem * query_rem = arg_rem( NULL, "Query (-q) options:" );
    struct arg_str *query_scripts= arg_str0(
        NULL,
        "scripts",
        "<str>",
        "Queries installed or uninstalled packages. \n" SPACE_27
        "<str>=pre|post|preun|postun" );
    query_scripts->hdr.flag |= ARG_HASOPTVALUE;
    query_scripts->sval[0] = default_query_scripts_arg;
    struct arg_str *query_format= arg_str0( NULL, "qf", "<str>", "Query format." );

    struct arg_lit *query_list= arg_lit0( "l", "list", "Lists files in the package." );

    struct arg_lit *upgrade= arg_lit0( "U", "upgrade", "Upgrades a package." );
    struct arg_lit *verify= arg_lit0( "V", "verify", "Verifies an installed packages." );
    struct arg_rem * verify_rem = arg_rem( NULL, "Verify (-V) options:" );

    struct arg_lit *all_opt= arg_lit0( "a", "all", "Queries all installed packages" );

    struct arg_file *file = arg_filen( NULL, NULL, "<package>", 0, 20, ".rpm file or installed package" );
    struct arg_end *end = arg_end( 20 );
    void *argtable[] =
    {help, verbose, version, root_opt, query_tags, query, query_rem, all_opt, query_scripts, query_list, query_format,
     upgrade, verify, verify_rem, file, end};

    int nerrors = arg_parse( argc, argv, argtable );

    if( nerrors )
    {
        arg_print_errors( errorDest, end, "minirpm" );
        return( 1 );
    }

    if( verbose->count != 0 )
    {
        *be_verbose =1;
    }

    if( version->count != 0 )
    {
        *todo = cmd_version;
    }

    if( help->count != 0 )
    {
        arg_print_syntax( outDest, argtable, NULL );
        fprintf( outDest, "\n" );

        arg_print_glossary( outDest, argtable, " %-25s %s\n" );
        *todo = cmd_help;
        goto bye;
    }

    if( query->count != 0 )
    {
        if( *todo != cmd_nothing )
        {
            fprintf( errorDest, "Only one command may be given on a command line.\n" );
            retval = 1;
            goto bye;
        }
        *todo = cmd_query_default;
    }
    if( verify->count != 0 )
    {
        if( *todo != cmd_nothing )
        {
            fprintf( errorDest, "Only one command may be given on a command line.\n" );
            retval = 1;
            goto bye;
        }
        *todo = cmd_verify;
    }
    if( all_opt->count != 0 )
    {
        if( *todo == cmd_query_default )
        {
            *todo = cmd_query_all;
        }
        else if( *todo == cmd_verify )
        {
            *todo = cmd_verify_all;
        }
        else
        {
            fprintf( errorDest, "The --all option must be used only after the query (-q) or verify (-v) options.\n" );
            retval = 1;
            goto bye;
        }

    }
    if( query_scripts->count != 0 )
    {
        if( *todo != cmd_query_default )
        {
            fprintf( errorDest, "The --scripts option must be used only after the query (-q) option.\n" );
            retval = 1;
            goto bye;
        }
        if( strcmp( query_scripts->sval[0], "all" ) == 0 )
        {
            *todo = cmd_query_all_scripts;
            goto bye;
        }
        if( strcmp( query_scripts->sval[0], "pre" ) == 0 )
        {
            *todo = cmd_query_pre_script;
            goto bye;
        }
        if( strcmp( query_scripts->sval[0], "post" ) == 0 )
        {
            *todo = cmd_query_post_script;
            goto bye;
        }
        if( strcmp( query_scripts->sval[0], "preun" ) == 0 )
        {
            *todo = cmd_query_preun_script;
            goto bye;
        }
        if( strcmp( query_scripts->sval[0], "postun" ) == 0 )
        {
            *todo = cmd_query_postun_script;
            goto bye;
        }
        fprintf( errorDest, "Unrecognized argument to --scripts.\n" );
        retval = 1;
        goto bye;
    }

    if( query_format->count != 0 )
    {
        if( *todo != cmd_query_default )
        {
            fprintf( errorDest, "The --qf option must be used only after the query (-q) option.\n" );
            retval = 1;
            goto bye;
        }
        *todo = cmd_query_format;
        *queryFormat = strdup( query_format->sval[0] );
    }

    if( query_tags->count != 0 )
    {
        if( *todo != cmd_nothing )
        {
            fprintf( errorDest, "Only one command may be given on a command line.\n" );
            retval = 1;
            goto bye;
        }
        *todo = cmd_query_tags;
    }

    if( query_list->count != 0 )
    {
        if( *todo != cmd_query_default )
        {
            fprintf( errorDest, "The --list option must be used only after the query (-q) option.\n" );
            retval = 1;
            goto bye;
        }
        *todo = cmd_query_list;
        goto bye;
    }
    if( upgrade->count != 0 )
    {
        if( *todo != cmd_nothing )
        {
            fprintf( errorDest, "Only one command may be given on a command line.\n" );
            retval = 1;
            goto bye;
        }
        *todo = cmd_upgrade;
    }

    bye:
    *fileNames = (const char**)( calloc( file->count, sizeof( char** ) ) );
    *numfilenames = 0;
    while( *numfilenames < file->count )
    {
        ( *fileNames )[*numfilenames] = strdup( file->filename[( *numfilenames )++] );
    }
    *root = strdup( root_opt->sval[0] );
    arg_freetable( argtable, sizeof( argtable )/sizeof( argtable[0] ) );

    return( retval );
}
